<?php

class DbItemQuery {

    private /* dbitem */ $prototype;
    private $filters = Array();
    private $order = Array();
    private $result = null;
    private $perpage = 100;
    private $page = 0;
    private $add_select = "";
    private $add_where = "";
    private $add_orderby = "";

    public static function __invoke($class) { // Enables invoke for php5.3
        return self::create($class);
    }

    public static function create(/* string */$class) {
        switch ($class) {
            case "User": $temp = new DbItemQuery(new User());
                break;
            case "ejemplo": $temp = new DbItemQuery(new ejemplo());
                break;
        }
        return $temp;
    }

    private function __construct($prototype) {
        $this->prototype = $prototype;
    }

    public function findId($id) {
        $pkey = $this->prototype->mapping->primaryKeyRule;
        $res = $this->filterBy($pkey->attributeName, "=", $id)->find();
        return $res[0];
    }

    public function filterBy($attribute, $operator, $operand) {
        array_push($this->filters, new Filter($attribute, $operator, $operand));
        return $this;
    }

    public function addCustom($select="", $where="", $orderby= "") {
        // Adds custom fields to select, where and orderby clauses
        $this->add_select = $select;
        $this->add_where = $where;
        $this->add_orderby = $orderby;
        return $this;
    }

    public function orderBy($atribute, $direction) {
        return $this;
    }

    public function setPerPage($items) {
        $this->perpage = $items;
        return $this;
    }

    public function setPage($page) {
        $this->page = $items;
        return $this;
    }

    private function buildQuery($count="0") {
        $table = " FROM " . $this->prototype->mapping->table;

        if ($count == "0") {
            $projection = "SELECT";
            foreach ($this->prototype->mapping->mappingRules as $r) {
                $projection = $projection . " " . $r->column . " as " . $r->attributeName . ", ";
            }
            $projection = substr($projection, 0, strlen($projection) - 2);
        } else {
            $projection = "SELECT COUNT(*) as contador";
        }


        $selection = " WHERE";
        foreach ($this->filters as $f) {
            $selection = $selection . " (" . $f->toSQL($this->prototype->mapping->mappingRules) . ") and";
        }
        $selection = substr($selection, 0, strlen($selection) - 4);

        $orderby = "";
        if (($this->add_orderby != "") && ($count == "0")) {
            $orderby = " ORDER BY " . $this->add_orderby;
        }

        if ($count == "0") {
            $paginado = " LIMIT " . $this->page . "," . $this->perpage;
        } else {
            $paginado = "";
        }
        return $projection . "" . $table . "" . $selection . "" . $orderby . "" . $paginado;
    }

    public function count() {
        // DO THE MAGIC
        $query = DBLink::getInstance()->query($this->buildQuery("1"));
        while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
            return $row["contador"];
        }
    }

    public function find() {
        // DO THE MAGIC
        $query = DBLink::getInstance()->query($this->buildQuery());
        $this->result = Array();
        while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
            array_push($this->result, $this->prototype->instance($row, $this->prototype->mapping));
        }
        return $this->result;
    }

}

?>
